/**
 * 
 */
package me.whily.nutzbook.module;

import java.awt.Color;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.sql.SQLException;
import java.util.Date;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;

import me.whily.nutzbook.bean.UserProfile;
import me.whily.nutzbook.util.ToolKit;

import org.apache.shiro.web.filter.authc.UserFilter;
import org.nutz.dao.Chain;
import org.nutz.dao.Cnd;
import org.nutz.dao.DaoException;
import org.nutz.dao.FieldFilter;
import org.nutz.dao.util.Daos;
import org.nutz.dao.util.blob.SimpleBlob;
import org.nutz.img.Images;
import org.nutz.ioc.loader.annotation.IocBean;
import org.nutz.lang.Streams;
import org.nutz.lang.Strings;
import org.nutz.lang.util.NutMap;
import org.nutz.log.Log;
import org.nutz.log.Logs;
import org.nutz.mvc.Mvcs;
import org.nutz.mvc.Scope;
import org.nutz.mvc.adaptor.JsonAdaptor;
import org.nutz.mvc.annotation.AdaptBy;
import org.nutz.mvc.annotation.At;
import org.nutz.mvc.annotation.Attr;
import org.nutz.mvc.annotation.By;
import org.nutz.mvc.annotation.Filters;
import org.nutz.mvc.annotation.GET;
import org.nutz.mvc.annotation.Ok;
import org.nutz.mvc.annotation.POST;
import org.nutz.mvc.annotation.Param;
import org.nutz.mvc.filter.CheckSession;
import org.nutz.mvc.impl.AdaptorErrorContext;
import org.nutz.mvc.upload.TempFile;
import org.nutz.mvc.upload.UploadAdaptor;

/**
 * @author Administrator
 * @since 2015-07-27 11:40:18
 */
@Filters(@By(type=CheckSession.class, args={"me", "/"}))
@IocBean
@At("/user/profile")
public class UserProfileModule extends BaseModule {
	
	private static final Log log = Logs.get();
	
	@Filters // 不需要先登录,很明显...
    @At("/active/mail")
    @GET
    @Ok("raw") // 为了简单起见,这里直接显示验证结果就好了
    public String activeMailCallback(@Param("token")String token, HttpSession session) {
        if (Strings.isBlank(token)) {
            return "请不要直接访问这个链接!!!";
        }
        if (token.length() < 10) {
            return "非法token";
        }
        try {
            token = ToolKit._3DES_decode(emailKEY, ToolKit.hexstr2bytearray(token));
            if (token == null)
                return "非法token";
            String[] tmp = token.split(",", 3);
            if (tmp.length != 3 || tmp[0].length() == 0 || tmp[1].length() == 0 || tmp[2].length() == 0)
                return "非法token";
            long time = Long.parseLong(tmp[2]);
            if (System.currentTimeMillis() - time > 10*60*1000) {
                return "该验证链接已经超时";
            }
            int userId = Integer.parseInt(tmp[0]);
            Cnd cnd = Cnd.where("userId", "=", userId).and("email", "=", tmp[1]);
            int re = dao.update(UserProfile.class, Chain.make("emailChecked", true), cnd);
            if (re == 1) {
                return "验证成功";
            }
            return "验证失败!!请重新验证!!";
        } catch (Throwable e) {
            log.debug("检查token时出错", e);
            return "非法token";
        }
    }
	
	@At("/active/mail")
    @POST
    public Object activeMail(@Attr(scope=Scope.SESSION, value="me")int userId,
            HttpServletRequest req) {
        NutMap re = new NutMap();
        UserProfile profile = get(userId);
        if (Strings.isBlank(profile.getEmail())) {
            return re.setv("ok", false).setv("msg", "你还没有填邮箱啊!");
        }
        String token = String.format("%s,%s,%s", userId, profile.getEmail(), System.currentTimeMillis());
        token = ToolKit._3DES_encode(emailKEY, token.getBytes());
        String url = req.getRequestURL() + "?token=" + token;
        String html = "<div>如果无法点击,请拷贝一下链接到浏览器中打开<p/>验证链接 %s</div>";
        html = String.format(html, url, url);
        try {
            boolean ok = emailService.send(profile.getEmail(), "XXX 验证邮件 by Nutzbook", html);
            if (!ok) {
                return re.setv("ok", false).setv("msg", "发送失败");
            }
        } catch (Throwable e) {
            log.debug("发送邮件失败", e);
            return re.setv("ok", false).setv("msg", "发送失败");
        }
        return re.setv("ok", true);
    }
	
	@At("/")
    @GET
    @Ok("jsp:jsp.user.profile")
    public UserProfile index(@Attr(scope=Scope.SESSION, value="me")int userId) {
        return get(userId);
    }
	
	@Ok("raw:jpg")
    @At("/avatar")
    @GET
    public Object readAvatar(@Attr(scope=Scope.SESSION, value="me")int userId, 
    		HttpServletRequest req) throws SQLException {
        UserProfile profile = Daos.ext(dao, FieldFilter.create(UserProfile.class, "^avatar$")).fetch(UserProfile.class, userId);
        if (profile == null || profile.getAvatar() == null) {
            return new File(req.getSession().getServletContext().getRealPath("/rs/user_avatar/none.jpg"));
        }
        return profile.getAvatar().getBinaryStream();
    }
	
	@AdaptBy(type=UploadAdaptor.class, args={"${app.root}/WEB-INF/tmp/user_avatar", "8192", "utf-8", "20000", "102400"})
    @POST
    @Ok(">>:/user/profile")
    @At("/avatar")
	public void uploadAvatar(@Param("file")TempFile tf,
			@Attr(scope=Scope.SESSION, value="me")int userId, AdaptorErrorContext err) {
		String msg = null;
		if (err != null && err.getAdaptorErr() != null) {
			msg = "文件大小不符合规定";
		} else if (tf == null) {
			msg = "空文件";
		} else {
			UserProfile profile = get(userId);
			try {
			BufferedImage image = Images.read(tf.getFile());
			image = Images.zoomScale(image, 128, 128, Color.WHITE);
			Images.writeJpeg(image, tf.getFile(), 0.8f);
			profile.setAvatar(new SimpleBlob(tf.getFile()){
				@Override
				public byte[] getBytes(long pos, int length)
						throws SQLException {
					if (pos == 1 && length == length()) {
						try {
							return Streams.readBytes(getBinaryStream());
						} catch (IOException e) {
						}
					}
					return super.getBytes(pos, length);
				}
			});
			dao.update(profile);
			} catch (DaoException e) {
				log.error("System Error", e);
				msg = "系统错误";
			} catch (Throwable e) {
				msg = "图片格式错误";
			}
		}
		
		if (msg != null) {
			Mvcs.getHttpSession().setAttribute("upload-error-msg", msg);
		}
	}

	@At
    public UserProfile get(@Attr(scope=Scope.SESSION, value="me")int userId) {
		UserProfile profile = Daos.ext(dao, FieldFilter.locked(UserFilter.class, "avatar")).
				fetch(UserProfile.class, userId);
		if (profile == null) {
			profile = new UserProfile();
			profile.setUserId(userId);
			profile.setCreateTime(new Date());
			profile.setUpdateTime(new Date());
			dao.insert(profile);
		}
		return profile;
    }
	 
	@At
	@Ok("void")
	@AdaptBy(type=JsonAdaptor.class)
    public void update(@Param("..")UserProfile profile, 
    		@Attr(scope=Scope.SESSION, value="me")int userId) {
		if (profile == null)
			return;
		profile.setUserId(userId);
		profile.setUpdateTime(new Date());
		profile.setAvatar(null);
		UserProfile old = get(userId);
		if (old.getEmail() == null) {
			profile.setEmailChecked(false);
		} else {
			if (profile.getEmail() == null) {
				profile.setEmail(old.getEmail());
				profile.setEmailChecked(old.isEmailChecked());
			} else if (!profile.getEmail().equals(old.getEmail())) {
				profile.setEmailChecked(false);
			}
		}
		Daos.ext(dao, FieldFilter.create(UserProfile.class, null, "avatar", true)).update(profile);
    }
	
}
